package com.yuantu.judiciary.serviceimpl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.yuantu.judiciary.dao.*;
import com.yuantu.judiciary.exception.enums.MonitorExceptionEnum;
import com.yuantu.judiciary.exception.enums.SmsExceptionEnum;
import com.yuantu.judiciary.model.api.MonitorEnterAddDTO;
import com.yuantu.judiciary.model.api.MonitorPersonAddDTO;
import com.yuantu.judiciary.model.api.MonitorQueryPageDTO;
import com.yuantu.judiciary.model.domain.*;
import com.yuantu.judiciary.model.dto.CaseSimpleDTO;
import com.yuantu.judiciary.model.dto.CaseSimpleDataDTO;
import com.yuantu.judiciary.model.dto.MonitorCaseDTO;
import com.yuantu.judiciary.model.dto.SendTimerQueryDataDTO;
import com.yuantu.judiciary.model.enums.CaseCategory;
import com.yuantu.judiciary.model.enums.MonitorType;
import com.yuantu.judiciary.model.enums.SmsTemplateType;
import com.yuantu.judiciary.model.vo.CaseTypeNumVO;
import com.yuantu.judiciary.model.vo.MonitorRecordAddVO;
import com.yuantu.judiciary.model.vo.MonitorRecordQueryVO;
import com.yuantu.judiciary.model.vo.MonitorRecordVO;
import com.yuantu.judiciary.service.IMonitorService;
import com.yuantu.judiciary.service.IOpenApiService;
import com.yuantu.judiciary.service.ISmsService;
import com.yuantu.judiciary.utils.AssertUtil;
import com.yuantu.judiciary.utils.Sm2Util;
import com.yuantu.judiciary.utils.StringUtil;
import com.yuantu.judiciary.utils.UrlUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


@Service
@Slf4j
@RequiredArgsConstructor
public class MonitorServiceImpl implements IMonitorService {


    private final IMonitorRecordDao monitorRecordDao;

    private final IMonitorEntityDao monitorEntityDao;

    private final IMonitorRecordFileDao monitorRecordFileDao;

    private final ISmsRecordDao smsRecordDao;

    private final IAccountDao accountDao;

    private final ISmsService smsService;
    private IOpenApiService openApiService;


    @Override
    public List<MonitorRecordVO> getMonitorList(Long accountId, MonitorRecordQueryVO data) {

        Date now = new Date();
        List<MonitorRecordVO> result = new ArrayList<>();
        List<MonitorRecordDO> monitorRecords = monitorRecordDao.findInfosByMonitorTypeAndCreatorIdAndIsPayTrue(data.getMonitorType(),
                accountId);
        if (Boolean.FALSE.equals(data.getIsHistory())) {
            monitorRecords = monitorRecords.stream().filter(s -> (now.before(s.getExpireTime()) ||
                    now.equals(s.getExpireTime())) && !s.getDisabled()).collect(Collectors.toList());
        } else {
            monitorRecords = monitorRecords.stream().filter(s -> now.after(s.getExpireTime()) || s.getDisabled()).collect(Collectors.toList());
        }
        for (MonitorRecordDO monitorRecord : monitorRecords) {
            String monitorContent = monitorRecord.getMonitorContent();
            MonitorPersonAddDTO monitorPerson = JSON.parseObject(monitorContent, MonitorPersonAddDTO.class);
            MonitorRecordVO monitor = new MonitorRecordVO();
            monitor.setName(monitorPerson.getName());
            monitor.setMonitorType(monitorRecord.getMonitorType());
            monitor.setMonitorRecordId(monitorRecord.getId());
            result.add(monitor);
        }
        return result;
    }

    @Override
    public Long addMonitor(MonitorRecordAddVO data, Long userId) {
        MonitorRecordDO monitorRecord = new MonitorRecordDO();
        MonitorPersonAddDTO monitorPersonAdd = new MonitorPersonAddDTO();
        monitorRecord.setMonitorType(data.getMonitorType());
        monitorPersonAdd.setName(data.getName());
        monitorPersonAdd.setId(data.getIdNumber());
        monitorRecord.setMonitorContent(JSON.toJSONString(monitorPersonAdd));
        monitorRecord.setCreateTime(new Date());
        monitorRecord.setCreatorId(userId);
        monitorRecord.setDisabled(false);
        monitorRecordDao.save(monitorRecord);
        return monitorRecord.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean removeMonitor(Long monitorId) {

        MonitorRecordDO monitorRecord = monitorRecordDao.findInfoByIdAndDisabledFalse(monitorId);
        String monitorContent = monitorRecord.getMonitorContent();
        List<MonitorRecordDO> monitorRecords = monitorRecordDao.findInfosByMonitorContentAndIsPayTrueAndDisabledFalse(monitorContent);
        if (monitorRecords.size() == 1) {
            MonitorEntityDO monitorEntity = monitorEntityDao.findInfoByMonitorContentAndMonitorType(monitorContent,
                    monitorRecord.getMonitorType());
            monitorEntityDao.removeInfoById(monitorEntity.getId());
            //调用外部监控移除接口
            if (MonitorType.PERSON.getValue().equals(monitorRecord.getMonitorType())) {
                MonitorPersonAddDTO monitorPersonAdd = JSON.parseObject(monitorContent, MonitorPersonAddDTO.class);
                openApiService.personRemoveMonitorProd(monitorPersonAdd);
            }
            if (MonitorType.ENTER.getValue().equals(monitorRecord.getMonitorType())) {
                MonitorPersonAddDTO monitorPersonAdd = JSON.parseObject(monitorContent, MonitorPersonAddDTO.class);
                MonitorEnterAddDTO monitorEnterAdd = new MonitorEnterAddDTO();
                monitorEnterAdd.setName(monitorPersonAdd.getName());
                openApiService.enterRemoveMonitorProd(monitorEnterAdd);
            }
        }
        monitorRecord.setDisabled(true);
        monitorRecordDao.save(monitorRecord);
        return true;
    }

    @Override
    public Boolean monitorFileAdd(Long monitorRecordId, String fileUrl) {
        MonitorRecordFileDO monitorRecordFile = new MonitorRecordFileDO();
        monitorRecordFile.setMonitorRecordId(monitorRecordId);
        monitorRecordFile.setFileUrl(fileUrl);
        monitorRecordFileDao.save(monitorRecordFile);
        return true;
    }

    @Override
    public MonitorCaseDTO monitorCaseDetail(String monitorSign) {
        if (StringUtil.isBlank(monitorSign)) {
            log.info("获取监控记录异常，监控签名为空！！！");
            return new MonitorCaseDTO();
        }
        SmsRecordDO smsRecord = smsRecordDao.findByRemarksAndDeletedFalse(monitorSign);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(smsRecord), SmsExceptionEnum.SMS_RECORD_NOT_EXIST);
        AssertUtil.assertTrue((smsRecord.getExpiresTime().getTime() >= System.currentTimeMillis()), SmsExceptionEnum.SMS_REPORT_EXPIRED);
        MonitorPersonAddDTO monitorContent = JSON.parseObject(smsRecord.getContent(), MonitorPersonAddDTO.class);
        MonitorEntityDO monitorEntity = monitorEntityDao.findInfoByMonitorContentAndMonitorType(JSON.toJSONString(monitorContent), StringUtil.isBlank(monitorContent.getId())
                ? MonitorType.ENTER.getValue() : MonitorType.PERSON.getValue());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(monitorEntity), MonitorExceptionEnum.MONITOR_ENTITY_NOT_EXIST);
        AssertUtil.assertTrue(!StringUtil.isBlank(monitorEntity.getResponseContent()), MonitorExceptionEnum.MONITOR_ENTITY_CASE_DETAIL_NOT_EXIST);
        return JSON.parseObject(monitorEntity.getResponseContent(), MonitorCaseDTO.class);
    }

    @Override
    public void monitorTimeQuery() {
        Date now = new Date();
        List<MonitorRecordDO> monitorRecords = monitorRecordDao.findInfosByIsPayTrueAndDisabledFalse();
        monitorRecords = monitorRecords.stream().filter(s -> now.before(s.getExpireTime()) || now.equals(s.getExpireTime())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(monitorRecords)) {
            return;
        }
        MonitorQueryPageDTO monitorQueryPage = new MonitorQueryPageDTO();
        monitorQueryPage.setPageIndex(1);
        monitorQueryPage.setPageSize(1000);
        monitorQueryPage.setQueryDate(now);
        //远程接口查询个人/企业监控案件信息
        List<CaseSimpleDataDTO> monitorPersonInfos = new ArrayList<>();
        try {
            monitorPersonInfos = openApiService.personQueryMonitorProd(monitorQueryPage).getRecords();
        } catch (Exception e) {
            log.info("远程接口查询个人监控案件信息失败，原因：" + e.getMessage(), e);
        }
        List<CaseSimpleDataDTO> monitorEnterInfos = new ArrayList<>();
        try {
            monitorEnterInfos = openApiService.enterQueryMonitorProd(monitorQueryPage).getRecords();
        } catch (Exception e) {
            log.info("远程接口查询企业监控案件信息失败，原因：" + e.getMessage(), e);
        }
        if (CollectionUtils.isEmpty(monitorPersonInfos) && CollectionUtils.isEmpty(monitorEnterInfos)) {
            return;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String nowStr = dateFormat.format(now);
        for (MonitorRecordDO monitorRecord : monitorRecords) {
            String monitorContent = monitorRecord.getMonitorContent();
            MonitorEntityDO monitorEntity = monitorEntityDao.findInfoByMonitorContentAndMonitorType(monitorContent, monitorRecord.getMonitorType());
            String responseContent = monitorEntity.getResponseContent();
            Date createTime = monitorEntity.getCreateTime();
            String createTimeStr = dateFormat.format(createTime);
            if (StringUtil.isNotBlank(responseContent) && nowStr.equals(createTimeStr)) {
                continue;
            }
            Integer monitorType = monitorRecord.getMonitorType();
            MonitorPersonAddDTO monitorInfo = JSON.parseObject(monitorContent, MonitorPersonAddDTO.class);
            String monitorStr;
            List<CaseSimpleDataDTO> caseSimpleInfos = new ArrayList<>();
            if (MonitorType.PERSON.getValue().equals(monitorType)) {
                monitorStr = monitorInfo.getName() + ":" + monitorInfo.getId();
                for (CaseSimpleDataDTO monitorPersonInfo : monitorPersonInfos) {
                    String name = monitorPersonInfo.getName();
                    if (name.equals(monitorStr)) {
                        caseSimpleInfos.add(monitorPersonInfo);
                    }
                }
            }
            if (MonitorType.ENTER.getValue().equals(monitorType)) {
                monitorStr = monitorInfo.getName();
                for (CaseSimpleDataDTO monitorEnterInfo : monitorEnterInfos) {
                    String name = monitorEnterInfo.getName();
                    if (name.equals(monitorStr)) {
                        caseSimpleInfos.add(monitorEnterInfo);
                    }
                }
            }
            if (!CollectionUtils.isEmpty(caseSimpleInfos)) {
                List<CaseSimpleDTO> caseSimpleList = new ArrayList<>();
                Map<String, List<CaseSimpleDataDTO>> caseSimpleMap = caseSimpleInfos.stream().collect(Collectors.
                        groupingBy(CaseSimpleDataDTO::getCase_type));
                for (String caseType : caseSimpleMap.keySet()) {
                    CaseSimpleDTO caseSimple = new CaseSimpleDTO();
                    List<CaseSimpleDataDTO> caseSimpleDataInfos = caseSimpleMap.get(caseType);
                    caseSimple.setCurrent(caseSimpleDataInfos.size());
                    caseSimple.setRecords(caseSimpleDataInfos);
                    caseSimple.setCaseType(caseType);
                    caseSimpleList.add(caseSimple);
                }
                MonitorCaseDTO monitorCase = new MonitorCaseDTO();
                monitorCase.setName(monitorInfo.getName());
                monitorCase.setCaseInfos(caseSimpleList);
                monitorEntity.setResponseContent(JSON.toJSONString(monitorCase));
                monitorEntity.setCreateTime(now);
                monitorEntityDao.save(monitorEntity);
            }
        }
    }

    @Override
    public void monitorTimeQueryResult() {
         Date now = new Date();
        List<MonitorRecordDO> monitorRecords = monitorRecordDao.findInfosByIsPayTrueAndDisabledFalse();
        monitorRecords = monitorRecords.stream().filter(s -> now.before(s.getExpireTime()) || now.equals(s.getExpireTime())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(monitorRecords)) {
            return;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);  // 设置当前日期
        calendar.add(Calendar.DAY_OF_MONTH, -1);  // 减去一天
        Date previousDay = calendar.getTime();
        List<Long> accountIds = monitorRecords.stream().map(MonitorRecordDO::getCreatorId).collect(Collectors.toList());
        Map<Long, IAccountDao.AccountUserInfo> accountUserInfoMap = accountDao.getAccountInfo(accountIds).stream().
                collect(Collectors.toMap(IAccountDao.AccountUserInfo::getAccountId, Function.identity()));
        for (MonitorRecordDO monitorRecord : monitorRecords) {
            String monitorContent = monitorRecord.getMonitorContent();
            MonitorEntityDO monitorEntity = monitorEntityDao.findInfoByMonitorContentAndCreateTime(monitorContent, previousDay);
            if (monitorEntity != null) {
                String responseContent = monitorEntity.getResponseContent();
                if (StringUtil.isNotBlank(responseContent)) {
                    MonitorCaseDTO monitorCaseInfo = JSON.parseObject(responseContent, MonitorCaseDTO.class);
                    List<CaseSimpleDTO> caseSimpleInfos = monitorCaseInfo.getCaseInfos();
                    caseSimpleInfos = caseSimpleInfos.stream().filter(s -> s.getCurrent() > 0).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(caseSimpleInfos)) {
                        //发送查看短信
                        String monitorSign = UrlUtil.getUniqueShortUrl(Sm2Util.encrypt(monitorContent));
                        String url = "https://admin.njxnet.com/person/#/?monitorSign" + monitorSign;
                        IAccountDao.AccountUserInfo accountUserInfo = accountUserInfoMap.get(monitorRecord.getCreatorId());
                        if (ObjectUtils.isEmpty(accountUserInfo)) {
                            continue;
                        }
                        String phone = accountUserInfo.getPhone();
                        SendTimerQueryDataDTO sendTimerQueryData = new SendTimerQueryDataDTO();
                        List<CaseTypeNumVO> caseTypeNumInfos = new ArrayList<>();
                        List<String> caseTypeInfos = new ArrayList<>();
                        for (CaseSimpleDTO caseSimpleInfo : caseSimpleInfos) {
                            CaseTypeNumVO caseTypeNum = new CaseTypeNumVO();
                            caseTypeNum.setCaseNum(caseSimpleInfo.getCurrent());
                            for (CaseCategory value : CaseCategory.values()) {
                                if (value.getCode().equals(caseSimpleInfo.getCaseType())) {
                                    caseTypeNum.setCaseType(value.getValue());
                                }
                            }
                            caseTypeNumInfos.add(caseTypeNum);
                        }
                        for (CaseTypeNumVO caseTypeNumInfo : caseTypeNumInfos) {
                            String caseTypeInfo = caseTypeNumInfo.getCaseNum() + "条" + caseTypeNumInfo.getCaseType();
                            caseTypeInfos.add(caseTypeInfo);
                        }
                        sendTimerQueryData.setContent(String.join(",", caseTypeInfos));
                        sendTimerQueryData.setName(JSON.parseObject(monitorContent, MonitorPersonAddDTO.class).getName());
                        sendTimerQueryData.setUrl(url);
                        try {
                            smsService.sendTimerMsgCode(phone, null, sendTimerQueryData, SmsTemplateType.TIMER_QUERY);
                            //保存新短信记录
                            SmsRecordDO smsRecord = buildSmsRecordDO(phone, monitorContent,
                                    monitorSign);
                            smsRecordDao.save(smsRecord);
                        } catch (Exception e) {
                            log.info("案件查询短信发送失败，发送人accountId: {}, 手机号：{}", monitorRecord.getCreatorId(), phone, e);
                        }
                    }
                }
            }
        }
    }

      private SmsRecordDO buildSmsRecordDO(String phone, String content, String remarks) {
        SmsRecordDO smsRecord = new SmsRecordDO();
        smsRecord.setPhone(phone);
        smsRecord.setContent(content);
        smsRecord.setType(SmsTemplateType.TIMER_QUERY);
        Timestamp currentTime = new Timestamp(System.currentTimeMillis());
        smsRecord.setCreateTime(currentTime);
        long expiresTime = 86400000L; // 24 * 60 * 60 * 1000 一天
        smsRecord.setExpiresTime(new Timestamp(currentTime.getTime() + expiresTime));
        smsRecord.setRemarks(remarks);
        return smsRecord;
    }

}
